﻿using Aliyun.OSS;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Net;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;

namespace ImgUpload
{
    public class AliyunService
    {
        private OssClient _client;
        private readonly ILogger<AliyunService> _logger;
        private readonly ImageService _imageService;
        private readonly OssOption _option;
        public AliyunService(IOptions<OssOption> option, ILogger<AliyunService> logger, ImageService imageService)
        {
            _option = option?.Value;
            _client = new OssClient(_option.Endpoint, _option.AccessKeyId, _option.AccessKeySecret);
            _logger = logger;
            _logger.LogDebug($"OssOption:{_option.ToJsonString()}");
            _imageService = imageService;
        }

        public string Upload(string Prefix, string fileName, Stream stream)
        {
            try
            {
                string fileNameMd5 = MD5Encrypt(fileName);
                string suffix = _imageService.GetImageSuffix(stream);
                string key = Prefix + "/" + fileNameMd5 + suffix;

                if (_option.IsCompress)
                    stream = CompressUpload(stream);

                var metadata = new ObjectMetadata();
                metadata.ContentType = "image/jpeg";

                //上传文件
                var result = _client.PutObject(_option.BucketName, key, stream, metadata);

                if (result.HttpStatusCode != HttpStatusCode.OK)
                {
                    string msg = GetCallbackResponse(result);
                    _logger.LogError($"上传失败:{msg}");
                    return "";
                }
                return key;
            }
            catch (Exception ex)
            {
                _logger.LogError($"ex:{ex.ToString()}");
            }
            return "";
        }
        /// <summary>
        /// 压缩文件
        /// </summary>
        /// <param name="Prefix"></param>
        /// <param name="stream"></param>
        /// <param name="fileNameMd5"></param>
        /// <returns></returns>
        public Stream CompressUpload(Stream stream)
        {
            Stream compressStream = stream;
            int size = Convert.ToInt32(stream.Length / 1024);
            //压缩
            if (size < 100)
                size = 0;
            else if (size >= 100 && size <= 300)
                size = Convert.ToInt32(size * 0.3);
            else
                size = Convert.ToInt32(size * 0.1);

            if (size > 0)
                compressStream = _imageService.CompressImage(stream, 99, size);

            //需要把其实位置设为0 要不然阿里云无法上传
            compressStream.Position = 0;
            return compressStream;
        }

        public byte[] DownLoad(string fileName)
        {
            try
            {
                try
                {
                    using (OssObject obj = _client.GetObject(_option.BucketName, fileName))
                    {
                        using (Stream stream = obj.Content)
                        {
                            using (Image image = Image.FromStream(stream))
                            {
                                return _imageService.ImageToBytes(image);
                            }
                        }
                    }
                }
                catch (Exception)
                {
                    //如果没有 显示默认图片
                    using (OssObject obj = _client.GetObject(_option.BucketName, "head/" + MD5Encrypt("default.png")))
                    {
                        using (Stream stream = obj.Content)
                        {
                            using (Image image = Image.FromStream(stream))
                            {
                                return _imageService.ImageToBytes(image);
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                _logger.LogError($"ex:{ex.ToString()}");
            }
            return new byte[0];
        }

        ///   <summary>
        ///   给一个字符串进行MD5加密
        ///   </summary>
        ///   <param   name="strText">待加密字符串</param>
        ///   <returns>加密后的字符串</returns>
        private string MD5Encrypt(string strText)
        {
            MD5 md5 = new MD5CryptoServiceProvider();
            byte[] result = md5.ComputeHash(Encoding.UTF8.GetBytes(strText));
            string str = BitConverter.ToString(result).Replace("-", "").ToLower();
            return str;
        }

        private string GetCallbackResponse(PutObjectResult putObjectResult)
        {
            string callbackResponse = null;
            using (var stream = putObjectResult.ResponseStream)
            {
                var buffer = new byte[4 * 1024];
                var bytesRead = stream.Read(buffer, 0, buffer.Length);
                callbackResponse = Encoding.Default.GetString(buffer, 0, bytesRead);
            }
            return callbackResponse;
        }
    }
}
